#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <net/route.h>

int netintf_get_status(const char *iface)
{
    int fd;
    struct ifreq ifr;
    int flags;

    // 创建socket
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0)
    {
        perror("socket");
        return -1;
    }

    // 设置interface_name
    strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);

    // 获取接口状态
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
    {
        perror("ioctl");
        close(fd);
        return -1;
    }

    close(fd);

    // 返回接口状态
    flags = ifr.ifr_flags & IFF_UP;
    if (flags)
    {
        return 1; // UP
    }
    else
    {
        return 0; // DOWN
    }
}

int netintf_set_status(const char *iface, int up)
{
    int fd;
    struct ifreq ifr;

    // 创建socket
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0)
    {
        perror("socket");
        return -1;
    }

    // 设置interface_name
    strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);

    // 获取接口状态
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
    {
        perror("ioctl");
        close(fd);
        return -1;
    }

    // 设置接口状态
    if (up)
    {
        ifr.ifr_flags |= IFF_UP;
    }
    else
    {
        ifr.ifr_flags &= ~IFF_UP;
    }

    // 设置接口状态
    if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
    {
        perror("ioctl");
        close(fd);
        return -1;
    }

    close(fd);

    return 0;
}

int netintf_get_speed(const char *iface)
{
    char path[64];
    int speed;
    FILE *fp;

    snprintf(path, sizeof(path), "/sys/class/net/%s/speed", iface);
    fp = fopen(path, "r");
    if (fp == NULL)
    {
        perror("fopen");
        return -1;
    }

    if (fscanf(fp, "%d", &speed) != 1)
    {
        perror("fscanf");
        fclose(fp);
        return -1;
    }

    fclose(fp);
    return speed;
}

int netintf_get_ip(char *intf, char *ip)
{
    int sock, ret = 0;
    struct ifreq ifr;
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        printf("%s socket failed\n", __FUNCTION__);
        return -1;
    }

    memset(&ifr, 0, sizeof(struct ifreq));
    strcpy(ifr.ifr_name, intf);
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_port = 0;
    if (ioctl(sock, SIOCGIFADDR, (caddr_t)&ifr, sizeof(struct ifreq)) != 0)
    {
        printf("%s ioctl failed\n", __FUNCTION__);
        ret = -1;
        goto last;
    }
    strcpy(ip, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
last:
    if (sock > 0)
    {
        close(sock);
    }
    return ret;
}

int netintf_get_netmask(char *intf, char *netmask)
{
    int sock, ret = 0;
    struct ifreq ifr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        printf("%s socket failed\n", __FUNCTION__);
        return -1;
    }

    memset(&ifr, 0, sizeof(struct ifreq));
    strcpy(ifr.ifr_name, intf);
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_port = 0;
    if (ioctl(sock, SIOCGIFNETMASK, (caddr_t)&ifr, sizeof(struct ifreq)) != 0)
    {
        printf("%s ioctl failed\n", __FUNCTION__);
        ret = -1;
        goto last;
    }
    strcpy(netmask, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
last:
    if (sock > 0)
    {
        close(sock);
    }
    return ret;
}

int netintf_get_mac(char *intf, char *mac)
{
    struct ifreq ifr;
    int sock, ret = 0;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("%s socket failed\n", __FUNCTION__);
        return -1;
    }
    strcpy(ifr.ifr_name, intf);
    if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
    {
        printf("%s ioctl failed\n", __FUNCTION__);
        ret = -1;
        goto last;
    }
    memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
last:
    if (sock > 0)
    {
        close(sock);
    }
    return ret;
}

int netintf_set_ip(char *intf, char *ip)
{
    int sock, ret;
    struct ifreq ifr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        printf("%s socket failed\n", __FUNCTION__);
        return -1;
    }

    memset(&ifr, 0, sizeof(struct ifreq));
    strcpy(ifr.ifr_name, intf);
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_port = 0;
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = inet_addr(ip);
    if (ioctl(sock, SIOCSIFADDR, (caddr_t)&ifr, sizeof(struct ifreq)) != 0)
    {
        printf("%s ioctl failed\n", __FUNCTION__);
        ret = -1;
    }
    if (sock > 0)
    {
        close(sock);
    }
    return ret;
}

int netintf_set_netmask(char *intf, char *netmask)
{
    int sock, ret = 0;
    struct ifreq ifr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        printf("%s socket failed\n", __FUNCTION__);
        return -1;
    }

    memset(&ifr, 0, sizeof(struct ifreq));
    strcpy(ifr.ifr_name, intf);
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_port = 0;
    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = inet_addr(netmask);
    if (ioctl(sock, SIOCSIFNETMASK, (caddr_t)&ifr, sizeof(struct ifreq)) != 0)
    {
        printf("%s ioctl failed\n", __FUNCTION__);
        ret = -1;
    }

    if (sock > 0)
    {
        close(sock);
    }
    return ret;
}

int netintf_set_mac(char *intf, char *mac_str)
{
    struct ifreq ifr;
    int sock, ret = 0;
    char mac[6];

    ret = netintf_set_status(intf, 0);
    if (ret < 0)
    {
        printf("%s down failed\n", __FUNCTION__);
        return -1;
    }

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("%s socket failed\n", __FUNCTION__);
        return -1;
    }
    ifr.ifr_addr.sa_family = AF_INET;
    // ARPHRD_ETHER
    ifr.ifr_hwaddr.sa_family = 1;
    strcpy(ifr.ifr_name, intf);
    sscanf(mac_str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
    memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
    if (ioctl(sock, SIOCSIFHWADDR, &ifr) < 0)
    {
        printf("%s ioctl failed\n", __FUNCTION__);
        ret = -1;
        goto last;
    }
    ret = netintf_set_status(intf, 1);
    if (ret < 0)
    {
        printf("%s up failed\n", __FUNCTION__);
        return -1;
    }
last:
    if (sock > 0)
    {
        close(sock);
    }
    return ret;
}

int netintf_get_gateway(char *iface, char *gatewayIP)
{
    FILE *fp;
    struct in_addr addr;
    char line[1024];
    char ifaceName[32];
    char ifaceGateway[32];
    long ipNum;

    // Open /proc/net/route file
    fp = fopen("/proc/net/route", "r");
    if (fp == NULL)
    {
        printf("Failed to open file /proc/net/route\n");
        return -1;
    }

    // Read each line and parse the information for the specified interface
    while (fgets(line, sizeof(line), fp) != NULL)
    {
        sscanf(line, "%s %*s %s", ifaceName, ifaceGateway);
        ipNum = strtol(ifaceGateway, NULL, 16);
        if (strcmp(ifaceName, iface) == 0 && ipNum > 0)
        {
            addr.s_addr = ipNum;
            strcpy(gatewayIP, inet_ntoa(addr));
            fclose(fp);
            return 0;
        }
    }

    // Interface not found
    fclose(fp);
    return -1;
}

int netintf_set_gateway(char *intf, char *gateway)
{
    int ret;
    char cmd[64];
    sprintf(cmd, "ip route add default via %s dev %s", gateway, intf);
    ret = system(cmd);
    ret = (ret != 0) ? -1 : 0;
    return ret;
}

int netintf_del_gateway(char *intf)
{
    int ret;
    char cmd[64], gateway[32];
    ret = netintf_get_gateway(intf, gateway);
    if (ret < 0)
    {
        return -1;
    }
    sprintf(cmd, "ip route del default via %s dev %s", gateway, intf);
    ret = system(cmd);
    ret = (ret != 0) ? -1 : 0;
    return ret;
}

#if 0

int main(void)
{
    char ip[32] = {0}, netmask[32] = {0}, mac[32] = {0}, gateway[32] = {0}, opt, intf[32];

    printf("1---获取网络接口信息\n");
    printf("2---设置网络接口信息\n");
    printf("3---网络接口网关测试\n");
    printf("4---网络接口开关测试\n");

    opt = getchar();

    printf("输入要测试的网络接口\n");
    scanf("%s", intf);
    getchar();
    switch (opt)
    {
    case '1':
        netintf_get_ip(intf, ip);
        netintf_get_netmask(intf, netmask);
        netintf_get_mac(intf, mac);
        printf("网络ip:%s\n", ip);
        printf("网络netmask:%s\n", netmask);
        printf("网络mac:%02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        printf("网络速度：%dMbps\n", netintf_get_speed(intf));
        break;

    case '2':
        printf("请输入你的IP\n");
        scanf("%s", ip);
        netintf_set_ip(intf, ip);
        printf("请输入你的netmask\n");
        scanf("%s", netmask);
        netintf_set_netmask(intf, netmask);
        printf("请输入你的mac\n");
        scanf("%s", mac);
        netintf_set_mac(intf, mac);
        printf("请输入你的网关\n");
        scanf("%s", gateway);
        netintf_set_gateway(intf, gateway);

        printf("获取设置网络信息\n");
        netintf_get_ip(intf, ip);
        netintf_get_netmask(intf, netmask);
        netintf_get_mac(intf, mac);
        netintf_get_gateway(intf, gateway);

        printf("ip:%s\n", ip);
        printf("netmask:%s\n", netmask);
        printf("mac:%02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        printf("gateway:%s\n", gateway);
        break;

    case '3':
        printf("接口状态:%d-----\n", netintf_get_status(intf));
        printf("回车关闭网络接口\n");
        getchar();
        netintf_set_status(intf, 0);

        printf("接口状态:%d-----\n", netintf_get_status(intf));
        sleep(1);
        printf("回车打开网络接口\n");
        getchar();
        netintf_set_status(intf, 1);
        printf("接口状态:%d-----\n", netintf_get_status(intf));
        break;

    case '4':
        printf("请输入你的gateway\n");
        scanf("%s", gateway);
        getchar();
        netintf_set_gateway(intf, gateway);
        netintf_get_gateway(intf, gateway);
        printf("获取网络接口默认网关:%s----\n", gateway);
        printf("回车开始删除网关---\n");
        getchar();
        netintf_del_gateway(intf);
        break;
    }
}

#endif